﻿using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection.Emit;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using WCS.Infrastructure.IOC;
using WCS.Infrastructure.Tools;
using WCS.Service.Interface;
using System.Text.Json.Nodes; // 新增
using System.IO; // 新增
using System.Security.Cryptography.X509Certificates; // 新增

namespace WCS.Service.Instance
{
    public class EpaylinksService
    {
        private readonly IConfiguration _configuration;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly HttpClient _httpClient;

        public EpaylinksService(IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
        {
            _configuration = configuration;
            _httpContextAccessor = httpContextAccessor;
            _httpClient = new HttpClient();
        }

        /// <summary>
        /// 易票联Post请求接口
        /// </summary>
        /// <param name="sentence"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public async Task<string> post(string sentence, string url)
        {

            using (HttpClient client = new HttpClient())
            {
                // 设置请求头
                client.DefaultRequestHeaders.Add("x-efps-sign-type", _configuration["PaymentApi:SignType"]);
                client.DefaultRequestHeaders.Add("x-efps-sign-no", _configuration["PaymentApi:SignNo"]);
                //国际算法：x-efps-sign= Base64_encode (RSAwithSHA256_sign (SignBody，商户国际私钥) )；
                client.DefaultRequestHeaders.Add("x-efps-sign", EncryptionUtility.RSACryption.RSASign(sentence, _configuration["PaymentApi:ExportKeyPassword"], _configuration["PaymentApi:PrivateKeyPath"]));
                client.DefaultRequestHeaders.Add("x-efps-timestamp", DateTime.Now.ToString("yyyyMMddHHmmss"));

                // 创建请求内容
                var content = new StringContent(sentence, Encoding.UTF8, "application/json");

                // 发送 POST 请求
                HttpResponseMessage response = await client.PostAsync(url, content);

                // 检查响应状态
                if (response.IsSuccessStatusCode)
                {
                    //获取返回签名
                    var resSigns = response.Headers.GetValues("x-efps-sign");
                    // 获取响应内容
                    string contentStr = await response.Content.ReadAsStringAsync();
                    if (resSigns != null && resSigns.Count() > 0)
                    {
                        // 获取返回签名
                        string response_sign = resSigns.First();
                        // 验签返回
                        Console.WriteLine("验签结果：" + EncryptionUtility.RSACryption.verifySign(contentStr, response_sign, _configuration["PaymentApi:PublicKeyPath"]));
                    }
                    Console.WriteLine("返回参数：" + contentStr);
                    return contentStr;
                }
                else
                {
                    Console.WriteLine($"请求失败，状态码: {response.StatusCode}消息：{await response.Content.ReadAsStringAsync()}");

                    return await response.Content.ReadAsStringAsync();
                }
            }
        }

        public async Task<string> PostRequest(object request, string apiPath)
        {
            // 从配置文件获取API基础URL
            var apiBaseUrl = _configuration["PaymentApi:BaseUrl"];
            var requestUrl = $"{apiBaseUrl}{apiPath}";

            // 创建HTTP请求
            var requestMessage = new HttpRequestMessage(HttpMethod.Post, requestUrl);

            // 添加通用请求头
            var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
            requestMessage.Headers.Add("x-efps-sign-no", EncryptionUtility.Decrypt(_configuration["PaymentApi:SignNo"]));
            requestMessage.Headers.Add("x-efps-sign-type", _configuration["PaymentApi:SignType"]);
            requestMessage.Headers.Add("x-efps-timestamp", timestamp);

            // 计算消息报文
            var messageBody = CalculateMessageBody(request);

            // 计算签名
            var sign = EncryptionUtility.RSACryption.RSASign(messageBody, _configuration["PaymentApi:ExportKeyPassword"], _configuration["PaymentApi:PrivateKeyPath"]);
            requestMessage.Headers.Add("x-efps-sign", sign);

            // 配置JSON序列化选项（驼峰命名）
            var options = new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase
            };

            // 设置请求体
            var jsonContent = JsonSerializer.Serialize(request, options);
            requestMessage.Content = new StringContent(jsonContent, Encoding.UTF8, "application/json");

            // 发送请求
            var response = await _httpClient.SendAsync(requestMessage);
            response.EnsureSuccessStatusCode();

            // 解析响应
            var responseContent = await response.Content.ReadAsStringAsync();
            return responseContent;
        }

        /// <summary>
        /// 商户信息Post请求接口（加密后）
        /// </summary>
        /// <param name="sentence"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<string> MerchantPostRequest(string sentence, string url)
        {
            // 构建请求消息
            var requestMessage = new HttpRequestMessage(HttpMethod.Post, url);
            var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
            requestMessage.Headers.Add("x-efps-sign-no", _configuration["PaymentApi:SignNo"]);
            requestMessage.Headers.Add("x-efps-sign-type", _configuration["PaymentApi:SignType"]);
            requestMessage.Headers.Add("x-efps-timestamp", timestamp);
            requestMessage.Headers.Add("x-efps-version", "1.0");

            var messageBody = EncryptSensitivePaper(sentence,"");

            // 计算签名
            var sign = EncryptionUtility.RSACryption.RSASign(messageBody, _configuration["PaymentApi:ExportKeyPassword"], _configuration["PaymentApi:PrivateKeyPath"]);
            requestMessage.Headers.Add("x-efps-sign", sign);

            // 设置请求体为加密后的报文
            requestMessage.Content = new StringContent(messageBody, Encoding.UTF8, "application/json");

            // 发送请求
            var response = await _httpClient.SendAsync(requestMessage);
            if (!response.IsSuccessStatusCode)
            {
                throw new Exception($"请求失败，状态码：{response.StatusCode}");
            }

            // 解析响应
            var responseContent = await response.Content.ReadAsStringAsync();
            return responseContent;
        }

        public async Task<string> MerPostRequest(string sentence, string url)
        {
            // 构建请求消息
            var requestMessage = new HttpRequestMessage(HttpMethod.Post, url);
            var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
            requestMessage.Headers.Add("x-efps-sign-no", _configuration["PaymentApi:SignNo"]);
            requestMessage.Headers.Add("x-efps-sign-type", _configuration["PaymentApi:SignType"]);
            requestMessage.Headers.Add("x-efps-timestamp", timestamp);
            requestMessage.Headers.Add("x-efps-version", "1.0");//_configuration["PaymentApi:Version"]

            // 生成加密密钥对：明文SM4密钥 + RSA加密后的密钥（用于头部与签名）
            string plainKey = "268891BFB7B760DDA9F0A9AE4EE01D75";
            var encryptedKey = EncryptionUtility.RSACryption.RSAEncrypt(plainKey,_configuration["PaymentApi:PublicKeyPath"]);

            //var (plainKey, encryptedKey) = GenerateEncryptionKeyPair();
            requestMessage.Headers.Add("x-efps-enc-key", encryptedKey);
        
            // 对 sentence 中的 paper 敏感字段进行 SM4 加密并替换
            var messageBody = EncryptSensitivePaper(sentence, plainKey);
        
            // 计算签名（使用加密后的报文）
            var sign = CalculateSignature(messageBody, timestamp, encryptedKey);
            requestMessage.Headers.Add("x-efps-sign", sign);
        
            // 设置请求体为加密后的报文
            requestMessage.Content = new StringContent(messageBody, Encoding.UTF8, "application/json");
        
            // 发送请求
            var response = await _httpClient.SendAsync(requestMessage);
            if (!response.IsSuccessStatusCode)
            {
                throw new Exception($"请求失败，状态码：{response.StatusCode}");
            }
        
            // 解析响应
            var responseContent = await response.Content.ReadAsStringAsync();
            return responseContent;
        }

        // 计算消息报文
        public string CalculateMessageBody(object request)
        {
            // 配置 JsonSerializerOptions 以使用驼峰命名法
            var options = new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase
            };
            var jsonContent = JsonSerializer.Serialize(request, options);
            return jsonContent;
        }

        // 生成加密密钥对：返回（SM4明文密钥，RSA加密后的密钥）
        // 方法：GenerateEncryptionKeyPair
        private (string PlainKey, string EncryptedKey) GenerateEncryptionKeyPair()
        {
            var randomKey = "268891BFB7B760DDA9F0A9AE4EE01D75";//Config.GenerateRandomKey(32); // 32位随机字符串
            var randomKeyBytes = Encoding.UTF8.GetBytes(randomKey);
        
            // 优先使用证书路径（PublicKeyPath）→ OAEP-SHA256
            var publicKeyPath = _configuration["PaymentApi:PublicKeyPath"];
            if (!string.IsNullOrWhiteSpace(publicKeyPath) && File.Exists(publicKeyPath))
            {
                var x509 = new X509Certificate2(publicKeyPath);
                using var rsa = x509.GetRSAPublicKey();
                var encryptedKeyBytes = rsa.Encrypt(randomKeyBytes, RSAEncryptionPadding.OaepSHA256);
                var encryptedKey = Convert.ToBase64String(encryptedKeyBytes);
                return (randomKey, encryptedKey);
            }
        
            // 兼容XML/PEM字符串（统一使用 OAEP-SHA256）
            var publicKey = _configuration["PaymentApi:YplInternationalPublicKey"];
            if (!string.IsNullOrWhiteSpace(publicKey))
            {
                if (publicKey.TrimStart().StartsWith("<"))
                {
                    using var rsaXml = new RSACryptoServiceProvider();
                    rsaXml.FromXmlString(publicKey);
                    var parms = rsaXml.ExportParameters(false);
                    using var rsa = RSA.Create();
                    rsa.ImportParameters(parms);
                    var encryptedKeyBytes = rsa.Encrypt(randomKeyBytes, RSAEncryptionPadding.OaepSHA256);
                    var encryptedKey = Convert.ToBase64String(encryptedKeyBytes);
                    return (randomKey, encryptedKey);
                }
                if (publicKey.Contains("BEGIN PUBLIC KEY") || publicKey.Contains("BEGIN RSA PUBLIC KEY"))
                {
                    using var rsaPem = RSA.Create();
                    rsaPem.ImportFromPem(publicKey.ToCharArray());
                    var encryptedKeyBytes = rsaPem.Encrypt(randomKeyBytes, RSAEncryptionPadding.OaepSHA256);
                    var encryptedKey = Convert.ToBase64String(encryptedKeyBytes);
                    return (randomKey, encryptedKey);
                }
            }
        
            throw new InvalidOperationException("未找到有效的公钥，请配置 PaymentApi:PublicKeyPath 或 YplInternationalPublicKey");
        }

        // 对 JSON 中的 paper 字段执行 Base64(SM4_Encrypt(明文, key))
        private string EncryptSensitivePaper(string sentence, string sm4Key)
        {
            try
            {
                var node = JsonNode.Parse(sentence) as JsonObject;
                if (node == null) return sentence;
            
                var paperNode = node["paper"];
                if (paperNode == null) return sentence;
            
                string paperPlain;
                if (paperNode is JsonValue jv && jv.TryGetValue<string>(out var strVal))
                {
                    paperPlain = strVal;
                }
                else
                {
                    paperPlain = paperNode!.ToJsonString();
                }
            
                //if (string.IsNullOrWhiteSpace(sm4Key)) return sentence;
                var cipherBase64 = EncryptionUtility.RSACryption.RSAEncrypt(paperPlain, _configuration["PaymentApi:PublicKeyPath"]);

                //SM4Utility sM4Utility = new SM4Utility();
                //var cipherBase64 = sM4Utility.Encrypt_ECB(paperPlain);
                //// 将字符串转换为字节序列
                //byte[] b = System.Text.Encoding.UTF8.GetBytes(cipherBase64);
                //// 将字节序列转换为Base64字符串
                //cipherBase64 = Convert.ToBase64String(b);
                node["paper"] = cipherBase64;
                return node.ToJsonString();
            }
            catch
            {
                return sentence;
            }
        }

        

        // 计算消息签名（x-efps-sign）
        public string CalculateSignature(string messageBody, string timestamp, string encryptionKey)
        {
            var version = _configuration["PaymentApi:Version"];
            if (version == "2.0")
            {
                var signBody = messageBody + timestamp + encryptionKey;

                // 使用PFX私钥签名
                var privateKeyPath = _configuration["PaymentApi:PrivateKeyPath"];
                var password = _configuration["PaymentApi:ExportKeyPassword"];
                var cert = new X509Certificate2(privateKeyPath, password, X509KeyStorageFlags.Exportable);
                using var privateKey = cert.GetRSAPrivateKey();
                var signData = privateKey.SignData(Encoding.UTF8.GetBytes(signBody), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                return Convert.ToBase64String(signData);
            }
            else
            {
                throw new NotSupportedException("x-efps-version=1.0 签名逻辑暂未实现");
            }
        }
    }
}
